【前言】
本系列為個人前端學習之路的學習筆記,在過往的學習過程中累積了很多筆記,如今想藉著IT邦幫忙這個平台做整理+再複習。
本系列標題一律以【】標示該篇文章主要涉及的內容,例如【JavaScript】、【Vue】等等。
若內容有誤,還麻煩各路大神不吝於點出問題,感激不敬。
在JavaScript中,不同於純值,物件是傳參考
let obj1 = {
num: 1
};
obj2 = obj1;
obj2.num = 2;
console.log(obj1.num); //2
在這個案例中,我們將obj賦值到obj2上,並且修改obj2屬性的值
但因為物件傳參考的特性,原本的obj1也會一起改到
為了避免這樣的情況,我們希望把兩個相同的物件分離(確實的複製一份,可以各自獨立修改)
這時候就要使用拷貝,通常分為淺層拷貝和深層拷貝
淺層拷貝只有複製第一層,第二層內容仍是指向原本的參考
如果物件內屬性的值是物件,那它的參考位置也會一同被複製過去,因此在這個案例中innerObj仍就是同一個物件
let obj1 = {
num: 1,
innerObj: {
text: "inner"
}
};
let obj2 = {};
for(let key in obj1){
obj2[ key ] = obj1[ key ];
}
obj2.num = 2;
obj2.innerObj.text = "淺層拷貝無法保護到";
console.log(obj1.num); //1
console.log(obj1.innerObj.text); //淺層拷貝無法保護到
在這個案例中obj1的num屬性在淺層拷貝時被拷貝到了obj2,因此修改obj2的num並不會讓obj1的num產生影響
但因為innerObj是物件,因此拷貝過去的也是參考位置,obj1和obj2的innerObj還是同一個物件,因此還是會互相影響
這裡列舉幾個淺層拷貝的方法,第一個就是上面用的:
let 新物件 = {}; //創造一個新的參考位置
//把舊物件的第一層屬性複製過去
for(let key in 舊物件){
新物件[ key ] = 舊物件[ key ];
}
此外,ES6也有新的寫法,為let 新物件 = Object.assign( {} , 舊物件 )
let obj2 = Object.assign({},obj1);
或是使用展開:
let obj2 = {...obj1};
深層拷貝會將新物件與舊物件完全徹底斷開關係
即便有第三第四層的物件也不會出現問題
let obj1 = {
num: 1,
innerObj: {
text: "inner"
}
};
let obj2 = JSON.parse(JSON.stringify(obj1));
obj2.num = 2;
obj2.innerObj.text = "深層拷貝才保護得到";
console.log(obj1.num); //1
console.log(obj1.innerObj.text); //inner
深層拷貝會透過JSON.parse
和JSON.stringify
將元物件轉成字串再轉回來,此時新物件與元物件就毫無關聯
之前我也研究過,順便來分享一下,有位大大提供另一種的解法說明~歡迎參考喔~
https://ithelp.ithome.com.tw/questions/10203585
感謝分享!